#include "i2c.h"

I2C::I2C(GPIO* scl,GPIO* sda)
{
	this->scl_pin = scl;
	this->sda_pin = sda;
}
void I2C::begin(uint32_t speed)
{
	this->speed = speed;
	scl_pin->mode(OUTPUT_OD);
	sda_pin->mode(OUTPUT_OD);
	scl_pin->set();
	sda_pin->set();
	config(speed);
}
int8_t I2C::config(uint32_t speed)
{
	switch(speed)
	{
	case 100000:
		delay_times = 32;
		break;
	case 200000:
		delay_times = 16;
		break;
	case 300000:
		delay_times = 8;
		break;
	case 400000:
		delay_times = 4;
		break;
	default:
		delay_times = speed;
	}
}
uint32_t I2C::read_config()
{

}
int8_t I2C::write_byte(uint8_t slave_address,uint8_t reg_address,uint8_t data)
{
	start();
	send_byte(slave_address);
	send_byte(data);
}
int8_t I2C::write_byte(uint8_t slave_address,uint8_t reg_address,uint8_t *data,uint16_t num_to_write)
{
	uint8_t i;
	start();
	send_byte(slave_address);
	for (i=0;i<num_to_write;i++)
	{
		send_byte(data[i]);
	}
}
	
int8_t I2C::read_byte(uint8_t slave_address,uint8_t reg_address,uint8_t *data)
{
	start();
	send_byte(slave_address);
	scl_pin->set();
	scl_pin->mode(INPUT_PU);
	while (0 == scl_pin->read())
	{
		delay_us(2);
	}
	scl_pin->mode(OUTPUT_OD);
	*data = receive_byte();
	send_no_ack();
	stop();
}
int8_t I2C::read_byte(uint8_t slave_address,uint8_t reg_address,uint8_t *data,uint16_t num_to_read)
{
	uint8_t i;
	start();
	send_byte(slave_address);
	scl_pin->set();
	scl_pin->mode(INPUT_PU);
	while (0 == scl_pin->read())
	{
		delay_us(delay_times);
	}
	scl_pin->mode(OUTPUT_OD);

	data[0] = receive_byte();
	for (i=1;i<num_to_read;i++)
	{	
		send_ack();
		data[i] = receive_byte();
	}
	send_no_ack();
	stop();
}
int8_t I2C::take_i2c_right(uint32_t speed)
{

}
int8_t I2C::release_i2c_right()
{

}
int8_t I2C::wait_dev_busy(uint8_t slave_address)
{

}
void I2C::start()
{
	sda_pin->set();
	scl_pin->set();
	sda_pin->reset();
	delay_us(delay_times);
	scl_pin->reset();
	delay_us(delay_times);
}
void I2C::stop()
{
	scl_pin->reset();
	sda_pin->reset();
	scl_pin->set();
	delay_us(delay_times);
	sda_pin->set();
	delay_us(delay_times);
}
int8_t I2C::send_ack()
{
	sda_pin->reset();
	scl_pin->set();
	delay_us(delay_times);
	scl_pin->reset();
	delay_us(delay_times);
}
int8_t I2C::send_no_ack()
{
	sda_pin->set();
	scl_pin->set();
	delay_us(delay_times);
	scl_pin->reset();
	delay_us(delay_times);
}
int8_t I2C::send_byte(uint8_t Byte)
{
	uint8_t i,ack;
	for(i=0;i<8;i++)
	{
		if(Byte & 0x80)
			sda_pin->set();
		else
			sda_pin->reset();
		Byte <<= 1;
		delay_us(delay_times);

		scl_pin->set();
		delay_us(delay_times);
		scl_pin->reset();
		delay_us(delay_times);
	}
	sda_pin->mode(INPUT_PU);
	scl_pin->set();
	if(1 == sda_pin->read())
		ack = ACK_OK_;
	else
		ack = ACK_ERROR_;
	scl_pin->reset();
	sda_pin->mode(OUTPUT_OD);
	sda_pin->set();
}


int8_t I2C::send_7bits_address(uint8_t slave_address)
{
	
}
uint8_t I2C::receive_byte()
{
	uint8_t i;
	uint8_t rec_byte = 0;

	sda_pin->set();
	sda_pin->mode(INPUT_PU);
	rec_byte = 0;
	for (i=0; i<8; i++)
	{
		rec_byte <<= 1;
		scl_pin->set();
		delay_us(delay_times);
		if(sda_pin->read())
			rec_byte |= 1;
		scl_pin->reset();
		delay_us(delay_times);
		
	}
	sda_pin->mode(OUTPUT_OD);
	sda_pin->set();
	/*scl_pin->reset();
	delay_us(delay_times);*/
	return rec_byte;

}
int8_t I2C::wait_ack()
{
	scl_pin->reset();
	sda_pin->set();
	scl_pin->set();
	
	if (sda_pin->read())
	{
		scl_pin->reset();
		return 0;
	}
	scl_pin->reset();
	return 1;
}

//SOFTI2C::SOFTI2C(GPIO* scl,GPIO* sda):I2C(scl,sda)
//{
//	/*this->scl_pin = scl;
//	this->sda_pin = scl;*/
//}